猫狗大战

本项目中,将对数据集中的猫狗进行分类。 数据源来自于kaggle比赛“Dogs vs. Cats Redux: Kernels Edition”。 数据集链接:https://www.kaggle.com/c/dogs-vs-cats-redux-kernels-edition/data 将对数据集进行预处理(剔除异常值、统一图片size等),然后利用keras提供的深度神经网络学习架构对猫狗数据集进行建模(二分类模型)。最后,利用优化后的模型在测试集上进行预测,并将预测结构提交到kaggle,目标达到kaggle排名的前10%。

一、探索数据集

数据集中图片大小是否一致?图片标签有哪些?这些标签是顺序排列还是随机排列?是否存在异常值(标签与图片内容不符)?探索数据集将有利于预处理数据,并是预测结果更准确。

1.1 读取数据

将train目录下训练集数据和test目录下测试集数据读入列表中(文件路径)

In [1]:
import matplotlib.pyplot as plt
import numpy as np
import math
import os
import shutil
import cv2
import sys
%matplotlib inline

train_image_path="./train/"
test_image_path="./test/"
train_image_list=[]
test_image_list=[]
rows = 299
cols = 299

# #解压图片   
# if os.path.exists("./train/"):
#     shutil.rmtree("./train/")
# os.system('unzip train.zip')
    
# if os.path.exists("./test/"):
#     shutil.rmtree("./test/")
# os.system('unzip test.zip')
    
#从目录中所有文件读入到列表中
def get_image_list(path_name, list_name):
    for file_name in os.listdir(path_name):
        list_name.append(os.path.join(path_name, file_name))

get_image_list(train_image_path, train_image_list)
get_image_list(test_image_path, test_image_list)
print("train image sample:{}\ntest image sample:{}".format(len(train_image_list),len(test_image_list)))
/home/ubuntu/anaconda2/envs/cv/lib/python3.5/site-packages/matplotlib/font_manager.py:278: UserWarning: Matplotlib is building the font cache using fc-list. This may take a moment.
  'Matplotlib is building the font cache using fc-list. '
train image sample:25000
test image sample:12500

1.2 实现显示列表中图片函数

实现显示图片函数,并从训练集和测试集中各随机挑选10张图片显示

In [2]:
def display_img(img_list, summary = True):
    fig = plt.figure(figsize=(15, 3 * math.ceil(len(img_list)/5)))
    for i in range(0, len(img_list)):
        img = cv2.imread(img_list[i])
        img = img[:,:,::-1]#BGR->RGB
        if summary:
            print("---->image: {}  - shape: {}".format(img_list[i], img.shape))
        ax = fig.add_subplot(math.ceil(len(img_list)/5),5,i+1)
        ax.set_title(os.path.basename(img_list[i]))
        ax.set_xticks([])
        ax.set_yticks([])
        img = cv2.resize(img, (128,128))
        ax.imshow(img)
    plt.show()

import random
random.seed(2018)
display_img(random.sample(train_image_list, 10))
display_img(random.sample(test_image_list, 10))
---->image: ./train/dog.3220.jpg  - shape: (242, 299, 3)
---->image: ./train/cat.2505.jpg  - shape: (359, 400, 3)
---->image: ./train/cat.10813.jpg  - shape: (416, 423, 3)
---->image: ./train/dog.10654.jpg  - shape: (53, 59, 3)
---->image: ./train/dog.6002.jpg  - shape: (400, 399, 3)
---->image: ./train/dog.7269.jpg  - shape: (240, 319, 3)
---->image: ./train/dog.2455.jpg  - shape: (499, 375, 3)
---->image: ./train/cat.7538.jpg  - shape: (331, 500, 3)
---->image: ./train/cat.23.jpg  - shape: (256, 334, 3)
---->image: ./train/dog.11559.jpg  - shape: (375, 499, 3)
---->image: ./test/6624.jpg  - shape: (375, 499, 3)
---->image: ./test/6836.jpg  - shape: (166, 240, 3)
---->image: ./test/2221.jpg  - shape: (375, 499, 3)
---->image: ./test/2218.jpg  - shape: (215, 249, 3)
---->image: ./test/10512.jpg  - shape: (100, 97, 3)
---->image: ./test/10603.jpg  - shape: (375, 499, 3)
---->image: ./test/10942.jpg  - shape: (270, 206, 3)
---->image: ./test/5152.jpg  - shape: (500, 374, 3)
---->image: ./test/8160.jpg  - shape: (499, 331, 3)
---->image: ./test/6536.jpg  - shape: (299, 400, 3)

1.3 随机展示的图片中没有异常值,那么整个数据集中是否存在异常值呢?我们看到,各个图片的size不同,那么异常值是否和图片的size有关?

下面我们绘制训练集图片size分布情况。

In [3]:
#实现获取图片像素函数
def get_pic_size_distribution(img_list):
    x_PX= np.zeros(25000)
    y_PX= np.zeros(25000)
    for i,item in enumerate(img_list):
        img = cv2.imread(item)
        x_PX[i]=img.shape[0]
        y_PX[i]=img.shape[1]
    return x_PX, y_PX
In [53]:
#实现展示图片size分布图函数
def show_pic_size_distribution( x_PX, y_PX ):
    plt.figure(figsize=(15,15))
    #设置lable,颜色
    plt.scatter(x_PX, y_PX, c='blue', label='px')
    #设置标题
    plt.title('pic_size_distribution')
    #设置坐标轴lable
    plt.xlabel('x_px')
    plt.ylabel('y_px')
    #设置legend
    plt.legend(loc=2)
    plt.show()
In [55]:
#展示训练集图片size分布
x_PX, y_PX = get_pic_size_distribution(train_image_list)
show_pic_size_distribution( x_PX, y_PX )

我们看到,几乎所有图片大小都集中在左下部分,有两个图片的size分布在右上角,那么这两个尺寸异常值是否就是图片异常值呢? 展示2张size异常的图片

In [17]:
abnormal=[]
for i in range(25000):
    if y_PX[i]>800:
        abnormal.append(train_image_list[i])
In [23]:
display_img(abnormal)
---->image: ./train/cat.835.jpg  - shape: (768, 1023, 3)
---->image: ./train/dog.2317.jpg  - shape: (702, 1050, 3)

我们看到,这两张尺寸异常的图片同样是正常的猫狗图片。那么我们如何定义异常值?ImageNet数据集中包含有猫狗的具体分类,对一个图片在载有ImageNet上预训练权值的xception模型上进行预测,如果其预测结果top50不包含猫狗真实的标签分类(图片预测值前50都没有正常分类),那么就将其视为异常值

二、数据预处理

经过初步探索数据集发现:图片大小不一致;图片命名有dog、cat;标签(图片命名)是按顺序排列(cat排在前边、dog排在后边);图片存在异常值(非猫非狗)。在预处理部分,我们将resize统一图片大小,剔除异常值,打乱样本顺序,生成标签(dog:1;cat:0)。

2.1 剔除异常值

利用Xception网络对训练集进行imagenet分类,如果topN不含有‘dog’‘cat’视为异常值

2.1.1 导入Xception模型(载入imagenet预训练权值)

In [3]:
from keras.applications import *
model_pre=xception.Xception(weights='imagenet')
Using TensorFlow backend.
Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.4/xception_weights_tf_dim_ordering_tf_kernels.h5
91889664/91884032 [==============================] - 1s 0us/step

2.1.2 生成imagenet中猫狗种类列表

ImageNet 1000个类具体内容,参考文献 https://blog.csdn.net/zhangjunbob/article/details/53258524

In [4]:
Dogs = [ 'n02085620','n02085782','n02085936','n02086079','n02086240','n02086646','n02086910','n02087046','n02087394','n02088094','n02088238',
        'n02088364','n02088466','n02088632','n02089078','n02089867','n02089973','n02090379','n02090622','n02090721','n02091032','n02091134',
        'n02091244','n02091467','n02091635','n02091831','n02092002','n02092339','n02093256','n02093428','n02093647','n02093754','n02093859',
        'n02093991','n02094114','n02094258','n02094433','n02095314','n02095570','n02095889','n02096051','n02096177','n02096294','n02096437',
        'n02096585','n02097047','n02097130','n02097209','n02097298','n02097474','n02097658','n02098105','n02098286','n02098413','n02099267',
        'n02099429','n02099601','n02099712','n02099849','n02100236','n02100583','n02100735','n02100877','n02101006','n02101388','n02101556',
        'n02102040','n02102177','n02102318','n02102480','n02102973','n02104029','n02104365','n02105056','n02105162','n02105251','n02105412',
        'n02105505','n02105641','n02105855','n02106030','n02106166','n02106382','n02106550','n02106662','n02107142','n02107312','n02107574',
        'n02107683','n02107908','n02108000','n02108089','n02108422','n02108551','n02108915','n02109047','n02109525','n02109961','n02110063',
        'n02110185','n02110341','n02110627','n02110806','n02110958','n02111129','n02111277','n02111500','n02111889','n02112018','n02112137',
        'n02112350','n02112706','n02113023','n02113186','n02113624','n02113712','n02113799','n02113978']
Cats=['n02123045','n02123159','n02123394','n02123597','n02124075','n02125311','n02127052']

2.1.3 实现判断是否为cat/dog判断函数

In [5]:
def batch_img(img_path_list, batch_size):
    '''split img_path_list into batches'''
    for begin in range(0, len(img_path_list), batch_size):
        end = min(begin+batch_size, len(img_path_list))
        yield img_path_list[begin:end]
        
def read_batch_img(batch_imgpath_list):
    '''read batch img and resize'''
    images = np.zeros((len(batch_imgpath_list), 299, 299, 3), dtype=np.uint8)
    for i in range(len(batch_imgpath_list)):
        img = cv2.imread(batch_imgpath_list[i])
        img = img[:,:,::-1]
        img = cv2.resize(img, (299,299))
        images[i] = img
    return images

def pred_pet(model, img_path_list, top_num, preprocess_input, decode_predictions, batch_size = 32):
    '''predict img
    #returns
        the list, will show pet or not
    '''
    ret = []
    for batch_imgpath_list in batch_img(img_path_list, batch_size):
        X = read_batch_img(batch_imgpath_list)
        X = preprocess_input(X)
        preds = model.predict(X)
        dps = decode_predictions(preds, top = top_num)
        for index in range(len(dps)):
            for i, val in enumerate(dps[index]):
                if (val[0] in Dogs) and ('dog' in batch_imgpath_list[index]):
                    ret.append(True)
                    break
                elif (val[0] in Cats) and ('cat' in batch_imgpath_list[index]):
                    ret.append(True)
                    break
                if i==len(dps[index])-1:
                    ret.append(False)
    return ret     

2.1.4 实现获取异常值函数

In [6]:
def get_abnormal_v(train_image_list, topN = 50):
    abnormal_v = []
    if os.path.exists("./abnormal.txt"):
        with open("./abnormal.txt", 'r') as f:
            items = f.readlines()
            abnormal_v = [item.strip('\n') for item in items]
    else:
        ret =[]
        ret = pred_pet(model_pre, train_image_list, topN, xception.preprocess_input, xception.decode_predictions)
        for i,val in enumerate(ret):
            if not val:
                abnormal_v.append(train_image_list[i])
        with open("./abnormal.txt", 'w') as f:
            for item in abnormal_v:
                f.write("{}\n".format(item))
    return abnormal_v

2.1.5 显示并剔除异常值

In [7]:
abnormal_v = get_abnormal_v(train_image_list, topN=50)
display_img(abnormal_v, summary = False)
train_image_list = [item for item in train_image_list if item not in abnormal_v]
for i in abnormal_v:
    os.remove(i) 

2.2 随机化数据

探索数据集时发现,样本是顺序排列的(猫在前、狗在后),因此需要对数据集进行随机化处理。

In [8]:
import random
random.shuffle(train_image_list)

2.3 读入数据

将图片读入内存,并生成对应的label,并将训练集图片分成5份,1份作为验证集,其余4份作为训练集。

In [9]:
 X = read_batch_img(train_image_list)
In [10]:
#生成对应label
def get_lables(image_list):
    labels = np.zeros(len(image_list), dtype=np.uint8)
    for i,item in enumerate(image_list):
        if "dog" in item:
            labels[i] = 1
        else:
            labels[i] = 0
    return labels
Y = get_lables(train_image_list)
In [11]:
#划分成训练集和验证集
val_X = X[:math.ceil(len(train_image_list)/5)]
val_Y = Y[:math.ceil(len(train_image_list)/5)]
train_X = X[math.ceil(len(train_image_list)/5):]
train_Y = Y[math.ceil(len(train_image_list)/5):]

三、构建网络

base model选用Xception,不包含top的分类器,随后在base model后边加一个二分类分类器

In [12]:
# create the base pre-trained model
base_model = xception.Xception(weights='imagenet', input_shape = (299,299,3), include_top=False, pooling='avg')

x = base_model.output

from keras.models import Model
from keras.layers import Dense
# 二分类分类器
predictions = Dense(1, activation='sigmoid')(x)
# this is the model we will train
model = Model(inputs=base_model.input, outputs=predictions)
model.summary()
#打印层数
for i, layer in enumerate(base_model.layers):
    print(i, layer.name)
Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.4/xception_weights_tf_dim_ordering_tf_kernels_notop.h5
83689472/83683744 [==============================] - 1s 0us/step
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_2 (InputLayer)            (None, 299, 299, 3)  0                                            
__________________________________________________________________________________________________
block1_conv1 (Conv2D)           (None, 149, 149, 32) 864         input_2[0][0]                    
__________________________________________________________________________________________________
block1_conv1_bn (BatchNormaliza (None, 149, 149, 32) 128         block1_conv1[0][0]               
__________________________________________________________________________________________________
block1_conv1_act (Activation)   (None, 149, 149, 32) 0           block1_conv1_bn[0][0]            
__________________________________________________________________________________________________
block1_conv2 (Conv2D)           (None, 147, 147, 64) 18432       block1_conv1_act[0][0]           
__________________________________________________________________________________________________
block1_conv2_bn (BatchNormaliza (None, 147, 147, 64) 256         block1_conv2[0][0]               
__________________________________________________________________________________________________
block1_conv2_act (Activation)   (None, 147, 147, 64) 0           block1_conv2_bn[0][0]            
__________________________________________________________________________________________________
block2_sepconv1 (SeparableConv2 (None, 147, 147, 128 8768        block1_conv2_act[0][0]           
__________________________________________________________________________________________________
block2_sepconv1_bn (BatchNormal (None, 147, 147, 128 512         block2_sepconv1[0][0]            
__________________________________________________________________________________________________
block2_sepconv2_act (Activation (None, 147, 147, 128 0           block2_sepconv1_bn[0][0]         
__________________________________________________________________________________________________
block2_sepconv2 (SeparableConv2 (None, 147, 147, 128 17536       block2_sepconv2_act[0][0]        
__________________________________________________________________________________________________
block2_sepconv2_bn (BatchNormal (None, 147, 147, 128 512         block2_sepconv2[0][0]            
__________________________________________________________________________________________________
conv2d_5 (Conv2D)               (None, 74, 74, 128)  8192        block1_conv2_act[0][0]           
__________________________________________________________________________________________________
block2_pool (MaxPooling2D)      (None, 74, 74, 128)  0           block2_sepconv2_bn[0][0]         
__________________________________________________________________________________________________
batch_normalization_5 (BatchNor (None, 74, 74, 128)  512         conv2d_5[0][0]                   
__________________________________________________________________________________________________
add_13 (Add)                    (None, 74, 74, 128)  0           block2_pool[0][0]                
                                                                 batch_normalization_5[0][0]      
__________________________________________________________________________________________________
block3_sepconv1_act (Activation (None, 74, 74, 128)  0           add_13[0][0]                     
__________________________________________________________________________________________________
block3_sepconv1 (SeparableConv2 (None, 74, 74, 256)  33920       block3_sepconv1_act[0][0]        
__________________________________________________________________________________________________
block3_sepconv1_bn (BatchNormal (None, 74, 74, 256)  1024        block3_sepconv1[0][0]            
__________________________________________________________________________________________________
block3_sepconv2_act (Activation (None, 74, 74, 256)  0           block3_sepconv1_bn[0][0]         
__________________________________________________________________________________________________
block3_sepconv2 (SeparableConv2 (None, 74, 74, 256)  67840       block3_sepconv2_act[0][0]        
__________________________________________________________________________________________________
block3_sepconv2_bn (BatchNormal (None, 74, 74, 256)  1024        block3_sepconv2[0][0]            
__________________________________________________________________________________________________
conv2d_6 (Conv2D)               (None, 37, 37, 256)  32768       add_13[0][0]                     
__________________________________________________________________________________________________
block3_pool (MaxPooling2D)      (None, 37, 37, 256)  0           block3_sepconv2_bn[0][0]         
__________________________________________________________________________________________________
batch_normalization_6 (BatchNor (None, 37, 37, 256)  1024        conv2d_6[0][0]                   
__________________________________________________________________________________________________
add_14 (Add)                    (None, 37, 37, 256)  0           block3_pool[0][0]                
                                                                 batch_normalization_6[0][0]      
__________________________________________________________________________________________________
block4_sepconv1_act (Activation (None, 37, 37, 256)  0           add_14[0][0]                     
__________________________________________________________________________________________________
block4_sepconv1 (SeparableConv2 (None, 37, 37, 728)  188672      block4_sepconv1_act[0][0]        
__________________________________________________________________________________________________
block4_sepconv1_bn (BatchNormal (None, 37, 37, 728)  2912        block4_sepconv1[0][0]            
__________________________________________________________________________________________________
block4_sepconv2_act (Activation (None, 37, 37, 728)  0           block4_sepconv1_bn[0][0]         
__________________________________________________________________________________________________
block4_sepconv2 (SeparableConv2 (None, 37, 37, 728)  536536      block4_sepconv2_act[0][0]        
__________________________________________________________________________________________________
block4_sepconv2_bn (BatchNormal (None, 37, 37, 728)  2912        block4_sepconv2[0][0]            
__________________________________________________________________________________________________
conv2d_7 (Conv2D)               (None, 19, 19, 728)  186368      add_14[0][0]                     
__________________________________________________________________________________________________
block4_pool (MaxPooling2D)      (None, 19, 19, 728)  0           block4_sepconv2_bn[0][0]         
__________________________________________________________________________________________________
batch_normalization_7 (BatchNor (None, 19, 19, 728)  2912        conv2d_7[0][0]                   
__________________________________________________________________________________________________
add_15 (Add)                    (None, 19, 19, 728)  0           block4_pool[0][0]                
                                                                 batch_normalization_7[0][0]      
__________________________________________________________________________________________________
block5_sepconv1_act (Activation (None, 19, 19, 728)  0           add_15[0][0]                     
__________________________________________________________________________________________________
block5_sepconv1 (SeparableConv2 (None, 19, 19, 728)  536536      block5_sepconv1_act[0][0]        
__________________________________________________________________________________________________
block5_sepconv1_bn (BatchNormal (None, 19, 19, 728)  2912        block5_sepconv1[0][0]            
__________________________________________________________________________________________________
block5_sepconv2_act (Activation (None, 19, 19, 728)  0           block5_sepconv1_bn[0][0]         
__________________________________________________________________________________________________
block5_sepconv2 (SeparableConv2 (None, 19, 19, 728)  536536      block5_sepconv2_act[0][0]        
__________________________________________________________________________________________________
block5_sepconv2_bn (BatchNormal (None, 19, 19, 728)  2912        block5_sepconv2[0][0]            
__________________________________________________________________________________________________
block5_sepconv3_act (Activation (None, 19, 19, 728)  0           block5_sepconv2_bn[0][0]         
__________________________________________________________________________________________________
block5_sepconv3 (SeparableConv2 (None, 19, 19, 728)  536536      block5_sepconv3_act[0][0]        
__________________________________________________________________________________________________
block5_sepconv3_bn (BatchNormal (None, 19, 19, 728)  2912        block5_sepconv3[0][0]            
__________________________________________________________________________________________________
add_16 (Add)                    (None, 19, 19, 728)  0           block5_sepconv3_bn[0][0]         
                                                                 add_15[0][0]                     
__________________________________________________________________________________________________
block6_sepconv1_act (Activation (None, 19, 19, 728)  0           add_16[0][0]                     
__________________________________________________________________________________________________
block6_sepconv1 (SeparableConv2 (None, 19, 19, 728)  536536      block6_sepconv1_act[0][0]        
__________________________________________________________________________________________________
block6_sepconv1_bn (BatchNormal (None, 19, 19, 728)  2912        block6_sepconv1[0][0]            
__________________________________________________________________________________________________
block6_sepconv2_act (Activation (None, 19, 19, 728)  0           block6_sepconv1_bn[0][0]         
__________________________________________________________________________________________________
block6_sepconv2 (SeparableConv2 (None, 19, 19, 728)  536536      block6_sepconv2_act[0][0]        
__________________________________________________________________________________________________
block6_sepconv2_bn (BatchNormal (None, 19, 19, 728)  2912        block6_sepconv2[0][0]            
__________________________________________________________________________________________________
block6_sepconv3_act (Activation (None, 19, 19, 728)  0           block6_sepconv2_bn[0][0]         
__________________________________________________________________________________________________
block6_sepconv3 (SeparableConv2 (None, 19, 19, 728)  536536      block6_sepconv3_act[0][0]        
__________________________________________________________________________________________________
block6_sepconv3_bn (BatchNormal (None, 19, 19, 728)  2912        block6_sepconv3[0][0]            
__________________________________________________________________________________________________
add_17 (Add)                    (None, 19, 19, 728)  0           block6_sepconv3_bn[0][0]         
                                                                 add_16[0][0]                     
__________________________________________________________________________________________________
block7_sepconv1_act (Activation (None, 19, 19, 728)  0           add_17[0][0]                     
__________________________________________________________________________________________________
block7_sepconv1 (SeparableConv2 (None, 19, 19, 728)  536536      block7_sepconv1_act[0][0]        
__________________________________________________________________________________________________
block7_sepconv1_bn (BatchNormal (None, 19, 19, 728)  2912        block7_sepconv1[0][0]            
__________________________________________________________________________________________________
block7_sepconv2_act (Activation (None, 19, 19, 728)  0           block7_sepconv1_bn[0][0]         
__________________________________________________________________________________________________
block7_sepconv2 (SeparableConv2 (None, 19, 19, 728)  536536      block7_sepconv2_act[0][0]        
__________________________________________________________________________________________________
block7_sepconv2_bn (BatchNormal (None, 19, 19, 728)  2912        block7_sepconv2[0][0]            
__________________________________________________________________________________________________
block7_sepconv3_act (Activation (None, 19, 19, 728)  0           block7_sepconv2_bn[0][0]         
__________________________________________________________________________________________________
block7_sepconv3 (SeparableConv2 (None, 19, 19, 728)  536536      block7_sepconv3_act[0][0]        
__________________________________________________________________________________________________
block7_sepconv3_bn (BatchNormal (None, 19, 19, 728)  2912        block7_sepconv3[0][0]            
__________________________________________________________________________________________________
add_18 (Add)                    (None, 19, 19, 728)  0           block7_sepconv3_bn[0][0]         
                                                                 add_17[0][0]                     
__________________________________________________________________________________________________
block8_sepconv1_act (Activation (None, 19, 19, 728)  0           add_18[0][0]                     
__________________________________________________________________________________________________
block8_sepconv1 (SeparableConv2 (None, 19, 19, 728)  536536      block8_sepconv1_act[0][0]        
__________________________________________________________________________________________________
block8_sepconv1_bn (BatchNormal (None, 19, 19, 728)  2912        block8_sepconv1[0][0]            
__________________________________________________________________________________________________
block8_sepconv2_act (Activation (None, 19, 19, 728)  0           block8_sepconv1_bn[0][0]         
__________________________________________________________________________________________________
block8_sepconv2 (SeparableConv2 (None, 19, 19, 728)  536536      block8_sepconv2_act[0][0]        
__________________________________________________________________________________________________
block8_sepconv2_bn (BatchNormal (None, 19, 19, 728)  2912        block8_sepconv2[0][0]            
__________________________________________________________________________________________________
block8_sepconv3_act (Activation (None, 19, 19, 728)  0           block8_sepconv2_bn[0][0]         
__________________________________________________________________________________________________
block8_sepconv3 (SeparableConv2 (None, 19, 19, 728)  536536      block8_sepconv3_act[0][0]        
__________________________________________________________________________________________________
block8_sepconv3_bn (BatchNormal (None, 19, 19, 728)  2912        block8_sepconv3[0][0]            
__________________________________________________________________________________________________
add_19 (Add)                    (None, 19, 19, 728)  0           block8_sepconv3_bn[0][0]         
                                                                 add_18[0][0]                     
__________________________________________________________________________________________________
block9_sepconv1_act (Activation (None, 19, 19, 728)  0           add_19[0][0]                     
__________________________________________________________________________________________________
block9_sepconv1 (SeparableConv2 (None, 19, 19, 728)  536536      block9_sepconv1_act[0][0]        
__________________________________________________________________________________________________
block9_sepconv1_bn (BatchNormal (None, 19, 19, 728)  2912        block9_sepconv1[0][0]            
__________________________________________________________________________________________________
block9_sepconv2_act (Activation (None, 19, 19, 728)  0           block9_sepconv1_bn[0][0]         
__________________________________________________________________________________________________
block9_sepconv2 (SeparableConv2 (None, 19, 19, 728)  536536      block9_sepconv2_act[0][0]        
__________________________________________________________________________________________________
block9_sepconv2_bn (BatchNormal (None, 19, 19, 728)  2912        block9_sepconv2[0][0]            
__________________________________________________________________________________________________
block9_sepconv3_act (Activation (None, 19, 19, 728)  0           block9_sepconv2_bn[0][0]         
__________________________________________________________________________________________________
block9_sepconv3 (SeparableConv2 (None, 19, 19, 728)  536536      block9_sepconv3_act[0][0]        
__________________________________________________________________________________________________
block9_sepconv3_bn (BatchNormal (None, 19, 19, 728)  2912        block9_sepconv3[0][0]            
__________________________________________________________________________________________________
add_20 (Add)                    (None, 19, 19, 728)  0           block9_sepconv3_bn[0][0]         
                                                                 add_19[0][0]                     
__________________________________________________________________________________________________
block10_sepconv1_act (Activatio (None, 19, 19, 728)  0           add_20[0][0]                     
__________________________________________________________________________________________________
block10_sepconv1 (SeparableConv (None, 19, 19, 728)  536536      block10_sepconv1_act[0][0]       
__________________________________________________________________________________________________
block10_sepconv1_bn (BatchNorma (None, 19, 19, 728)  2912        block10_sepconv1[0][0]           
__________________________________________________________________________________________________
block10_sepconv2_act (Activatio (None, 19, 19, 728)  0           block10_sepconv1_bn[0][0]        
__________________________________________________________________________________________________
block10_sepconv2 (SeparableConv (None, 19, 19, 728)  536536      block10_sepconv2_act[0][0]       
__________________________________________________________________________________________________
block10_sepconv2_bn (BatchNorma (None, 19, 19, 728)  2912        block10_sepconv2[0][0]           
__________________________________________________________________________________________________
block10_sepconv3_act (Activatio (None, 19, 19, 728)  0           block10_sepconv2_bn[0][0]        
__________________________________________________________________________________________________
block10_sepconv3 (SeparableConv (None, 19, 19, 728)  536536      block10_sepconv3_act[0][0]       
__________________________________________________________________________________________________
block10_sepconv3_bn (BatchNorma (None, 19, 19, 728)  2912        block10_sepconv3[0][0]           
__________________________________________________________________________________________________
add_21 (Add)                    (None, 19, 19, 728)  0           block10_sepconv3_bn[0][0]        
                                                                 add_20[0][0]                     
__________________________________________________________________________________________________
block11_sepconv1_act (Activatio (None, 19, 19, 728)  0           add_21[0][0]                     
__________________________________________________________________________________________________
block11_sepconv1 (SeparableConv (None, 19, 19, 728)  536536      block11_sepconv1_act[0][0]       
__________________________________________________________________________________________________
block11_sepconv1_bn (BatchNorma (None, 19, 19, 728)  2912        block11_sepconv1[0][0]           
__________________________________________________________________________________________________
block11_sepconv2_act (Activatio (None, 19, 19, 728)  0           block11_sepconv1_bn[0][0]        
__________________________________________________________________________________________________
block11_sepconv2 (SeparableConv (None, 19, 19, 728)  536536      block11_sepconv2_act[0][0]       
__________________________________________________________________________________________________
block11_sepconv2_bn (BatchNorma (None, 19, 19, 728)  2912        block11_sepconv2[0][0]           
__________________________________________________________________________________________________
block11_sepconv3_act (Activatio (None, 19, 19, 728)  0           block11_sepconv2_bn[0][0]        
__________________________________________________________________________________________________
block11_sepconv3 (SeparableConv (None, 19, 19, 728)  536536      block11_sepconv3_act[0][0]       
__________________________________________________________________________________________________
block11_sepconv3_bn (BatchNorma (None, 19, 19, 728)  2912        block11_sepconv3[0][0]           
__________________________________________________________________________________________________
add_22 (Add)                    (None, 19, 19, 728)  0           block11_sepconv3_bn[0][0]        
                                                                 add_21[0][0]                     
__________________________________________________________________________________________________
block12_sepconv1_act (Activatio (None, 19, 19, 728)  0           add_22[0][0]                     
__________________________________________________________________________________________________
block12_sepconv1 (SeparableConv (None, 19, 19, 728)  536536      block12_sepconv1_act[0][0]       
__________________________________________________________________________________________________
block12_sepconv1_bn (BatchNorma (None, 19, 19, 728)  2912        block12_sepconv1[0][0]           
__________________________________________________________________________________________________
block12_sepconv2_act (Activatio (None, 19, 19, 728)  0           block12_sepconv1_bn[0][0]        
__________________________________________________________________________________________________
block12_sepconv2 (SeparableConv (None, 19, 19, 728)  536536      block12_sepconv2_act[0][0]       
__________________________________________________________________________________________________
block12_sepconv2_bn (BatchNorma (None, 19, 19, 728)  2912        block12_sepconv2[0][0]           
__________________________________________________________________________________________________
block12_sepconv3_act (Activatio (None, 19, 19, 728)  0           block12_sepconv2_bn[0][0]        
__________________________________________________________________________________________________
block12_sepconv3 (SeparableConv (None, 19, 19, 728)  536536      block12_sepconv3_act[0][0]       
__________________________________________________________________________________________________
block12_sepconv3_bn (BatchNorma (None, 19, 19, 728)  2912        block12_sepconv3[0][0]           
__________________________________________________________________________________________________
add_23 (Add)                    (None, 19, 19, 728)  0           block12_sepconv3_bn[0][0]        
                                                                 add_22[0][0]                     
__________________________________________________________________________________________________
block13_sepconv1_act (Activatio (None, 19, 19, 728)  0           add_23[0][0]                     
__________________________________________________________________________________________________
block13_sepconv1 (SeparableConv (None, 19, 19, 728)  536536      block13_sepconv1_act[0][0]       
__________________________________________________________________________________________________
block13_sepconv1_bn (BatchNorma (None, 19, 19, 728)  2912        block13_sepconv1[0][0]           
__________________________________________________________________________________________________
block13_sepconv2_act (Activatio (None, 19, 19, 728)  0           block13_sepconv1_bn[0][0]        
__________________________________________________________________________________________________
block13_sepconv2 (SeparableConv (None, 19, 19, 1024) 752024      block13_sepconv2_act[0][0]       
__________________________________________________________________________________________________
block13_sepconv2_bn (BatchNorma (None, 19, 19, 1024) 4096        block13_sepconv2[0][0]           
__________________________________________________________________________________________________
conv2d_8 (Conv2D)               (None, 10, 10, 1024) 745472      add_23[0][0]                     
__________________________________________________________________________________________________
block13_pool (MaxPooling2D)     (None, 10, 10, 1024) 0           block13_sepconv2_bn[0][0]        
__________________________________________________________________________________________________
batch_normalization_8 (BatchNor (None, 10, 10, 1024) 4096        conv2d_8[0][0]                   
__________________________________________________________________________________________________
add_24 (Add)                    (None, 10, 10, 1024) 0           block13_pool[0][0]               
                                                                 batch_normalization_8[0][0]      
__________________________________________________________________________________________________
block14_sepconv1 (SeparableConv (None, 10, 10, 1536) 1582080     add_24[0][0]                     
__________________________________________________________________________________________________
block14_sepconv1_bn (BatchNorma (None, 10, 10, 1536) 6144        block14_sepconv1[0][0]           
__________________________________________________________________________________________________
block14_sepconv1_act (Activatio (None, 10, 10, 1536) 0           block14_sepconv1_bn[0][0]        
__________________________________________________________________________________________________
block14_sepconv2 (SeparableConv (None, 10, 10, 2048) 3159552     block14_sepconv1_act[0][0]       
__________________________________________________________________________________________________
block14_sepconv2_bn (BatchNorma (None, 10, 10, 2048) 8192        block14_sepconv2[0][0]           
__________________________________________________________________________________________________
block14_sepconv2_act (Activatio (None, 10, 10, 2048) 0           block14_sepconv2_bn[0][0]        
__________________________________________________________________________________________________
global_average_pooling2d_1 (Glo (None, 2048)         0           block14_sepconv2_act[0][0]       
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, 1)            2049        global_average_pooling2d_1[0][0] 
==================================================================================================
Total params: 20,863,529
Trainable params: 20,809,001
Non-trainable params: 54,528
__________________________________________________________________________________________________
0 input_2
1 block1_conv1
2 block1_conv1_bn
3 block1_conv1_act
4 block1_conv2
5 block1_conv2_bn
6 block1_conv2_act
7 block2_sepconv1
8 block2_sepconv1_bn
9 block2_sepconv2_act
10 block2_sepconv2
11 block2_sepconv2_bn
12 conv2d_5
13 block2_pool
14 batch_normalization_5
15 add_13
16 block3_sepconv1_act
17 block3_sepconv1
18 block3_sepconv1_bn
19 block3_sepconv2_act
20 block3_sepconv2
21 block3_sepconv2_bn
22 conv2d_6
23 block3_pool
24 batch_normalization_6
25 add_14
26 block4_sepconv1_act
27 block4_sepconv1
28 block4_sepconv1_bn
29 block4_sepconv2_act
30 block4_sepconv2
31 block4_sepconv2_bn
32 conv2d_7
33 block4_pool
34 batch_normalization_7
35 add_15
36 block5_sepconv1_act
37 block5_sepconv1
38 block5_sepconv1_bn
39 block5_sepconv2_act
40 block5_sepconv2
41 block5_sepconv2_bn
42 block5_sepconv3_act
43 block5_sepconv3
44 block5_sepconv3_bn
45 add_16
46 block6_sepconv1_act
47 block6_sepconv1
48 block6_sepconv1_bn
49 block6_sepconv2_act
50 block6_sepconv2
51 block6_sepconv2_bn
52 block6_sepconv3_act
53 block6_sepconv3
54 block6_sepconv3_bn
55 add_17
56 block7_sepconv1_act
57 block7_sepconv1
58 block7_sepconv1_bn
59 block7_sepconv2_act
60 block7_sepconv2
61 block7_sepconv2_bn
62 block7_sepconv3_act
63 block7_sepconv3
64 block7_sepconv3_bn
65 add_18
66 block8_sepconv1_act
67 block8_sepconv1
68 block8_sepconv1_bn
69 block8_sepconv2_act
70 block8_sepconv2
71 block8_sepconv2_bn
72 block8_sepconv3_act
73 block8_sepconv3
74 block8_sepconv3_bn
75 add_19
76 block9_sepconv1_act
77 block9_sepconv1
78 block9_sepconv1_bn
79 block9_sepconv2_act
80 block9_sepconv2
81 block9_sepconv2_bn
82 block9_sepconv3_act
83 block9_sepconv3
84 block9_sepconv3_bn
85 add_20
86 block10_sepconv1_act
87 block10_sepconv1
88 block10_sepconv1_bn
89 block10_sepconv2_act
90 block10_sepconv2
91 block10_sepconv2_bn
92 block10_sepconv3_act
93 block10_sepconv3
94 block10_sepconv3_bn
95 add_21
96 block11_sepconv1_act
97 block11_sepconv1
98 block11_sepconv1_bn
99 block11_sepconv2_act
100 block11_sepconv2
101 block11_sepconv2_bn
102 block11_sepconv3_act
103 block11_sepconv3
104 block11_sepconv3_bn
105 add_22
106 block12_sepconv1_act
107 block12_sepconv1
108 block12_sepconv1_bn
109 block12_sepconv2_act
110 block12_sepconv2
111 block12_sepconv2_bn
112 block12_sepconv3_act
113 block12_sepconv3
114 block12_sepconv3_bn
115 add_23
116 block13_sepconv1_act
117 block13_sepconv1
118 block13_sepconv1_bn
119 block13_sepconv2_act
120 block13_sepconv2
121 block13_sepconv2_bn
122 conv2d_8
123 block13_pool
124 batch_normalization_8
125 add_24
126 block14_sepconv1
127 block14_sepconv1_bn
128 block14_sepconv1_act
129 block14_sepconv2
130 block14_sepconv2_bn
131 block14_sepconv2_act
132 global_average_pooling2d_1
In [13]:
from keras.utils import plot_model
plot_model(model, to_file='model.png')
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
SVG(model_to_dot(model).create(prog='dot', format='svg'))
Out[13]:
G 139724826492320 input_2: InputLayer 139727822589232 block1_conv1: Conv2D 139724826492320->139727822589232 139724826492712 block1_conv1_bn: BatchNormalization 139727822589232->139724826492712 139724826672376 block1_conv1_act: Activation 139724826492712->139724826672376 139724826033624 block1_conv2: Conv2D 139724826672376->139724826033624 139724826639608 block1_conv2_bn: BatchNormalization 139724826033624->139724826639608 139724825430000 block1_conv2_act: Activation 139724826639608->139724825430000 139724826107632 block2_sepconv1: SeparableConv2D 139724825430000->139724826107632 139724827810056 conv2d_5: Conv2D 139724825430000->139724827810056 139724828306120 block2_sepconv1_bn: BatchNormalization 139724826107632->139724828306120 139724826313952 block2_sepconv2_act: Activation 139724828306120->139724826313952 139724827982984 block2_sepconv2: SeparableConv2D 139724826313952->139724827982984 139724828471248 block2_sepconv2_bn: BatchNormalization 139724827982984->139724828471248 139724828791920 block2_pool: MaxPooling2D 139724828471248->139724828791920 139724827811064 batch_normalization_5: BatchNormalization 139724827810056->139724827811064 139724829871968 add_13: Add 139724828791920->139724829871968 139724827811064->139724829871968 139724830358048 block3_sepconv1_act: Activation 139724829871968->139724830358048 139724826031944 conv2d_6: Conv2D 139724829871968->139724826031944 139727822772880 block3_sepconv1: SeparableConv2D 139724830358048->139727822772880 139724830479248 block3_sepconv1_bn: BatchNormalization 139727822772880->139724830479248 139724831136680 block3_sepconv2_act: Activation 139724830479248->139724831136680 139724831264216 block3_sepconv2: SeparableConv2D 139724831136680->139724831264216 139724826672880 block3_sepconv2_bn: BatchNormalization 139724831264216->139724826672880 139724830244256 block3_pool: MaxPooling2D 139724826672880->139724830244256 139724464683216 batch_normalization_6: BatchNormalization 139724826031944->139724464683216 139724831925640 add_14: Add 139724830244256->139724831925640 139724464683216->139724831925640 139724464013888 block4_sepconv1_act: Activation 139724831925640->139724464013888 139724826636640 conv2d_7: Conv2D 139724831925640->139724826636640 139724464100296 block4_sepconv1: SeparableConv2D 139724464013888->139724464100296 139724464396888 block4_sepconv1_bn: BatchNormalization 139724464100296->139724464396888 139724464329616 block4_sepconv2_act: Activation 139724464396888->139724464329616 139724464457768 block4_sepconv2: SeparableConv2D 139724464329616->139724464457768 139724464566224 block4_sepconv2_bn: BatchNormalization 139724464457768->139724464566224 139724465004896 block4_pool: MaxPooling2D 139724464566224->139724465004896 139724832226160 batch_normalization_7: BatchNormalization 139724826636640->139724832226160 139724464945416 add_15: Add 139724465004896->139724464945416 139724832226160->139724464945416 139724464800096 block5_sepconv1_act: Activation 139724464945416->139724464800096 139724465644880 add_16: Add 139724464945416->139724465644880 139724464825568 block5_sepconv1: SeparableConv2D 139724464800096->139724464825568 139724465176704 block5_sepconv1_bn: BatchNormalization 139724464825568->139724465176704 139724465243416 block5_sepconv2_act: Activation 139724465176704->139724465243416 139724465244032 block5_sepconv2: SeparableConv2D 139724465243416->139724465244032 139724465532712 block5_sepconv2_bn: BatchNormalization 139724465244032->139724465532712 139724465466504 block5_sepconv3_act: Activation 139724465532712->139724465466504 139724465411744 block5_sepconv3: SeparableConv2D 139724465466504->139724465411744 139724465784984 block5_sepconv3_bn: BatchNormalization 139724465411744->139724465784984 139724465784984->139724465644880 139724464802000 block6_sepconv1_act: Activation 139724465644880->139724464802000 139724466602504 add_17: Add 139724465644880->139724466602504 139724465582432 block6_sepconv1: SeparableConv2D 139724464802000->139724465582432 139724465981984 block6_sepconv1_bn: BatchNormalization 139724465582432->139724465981984 139724465906912 block6_sepconv2_act: Activation 139724465981984->139724465906912 139724465875264 block6_sepconv2: SeparableConv2D 139724465906912->139724465875264 139724466251648 block6_sepconv2_bn: BatchNormalization 139724465875264->139724466251648 139724466104640 block6_sepconv3_act: Activation 139724466251648->139724466104640 139724466140216 block6_sepconv3: SeparableConv2D 139724466104640->139724466140216 139724466479344 block6_sepconv3_bn: BatchNormalization 139724466140216->139724466479344 139724466479344->139724466602504 139724465584952 block7_sepconv1_act: Activation 139724466602504->139724465584952 139724467530048 add_18: Add 139724466602504->139724467530048 139724466362240 block7_sepconv1: SeparableConv2D 139724465584952->139724466362240 139724466717584 block7_sepconv1_bn: BatchNormalization 139724466362240->139724466717584 139724467093968 block7_sepconv2_act: Activation 139724466717584->139724467093968 139724467120784 block7_sepconv2: SeparableConv2D 139724467093968->139724467120784 139724466952792 block7_sepconv2_bn: BatchNormalization 139724467120784->139724466952792 139724467355488 block7_sepconv3_act: Activation 139724466952792->139724467355488 139724467238784 block7_sepconv3: SeparableConv2D 139724467355488->139724467238784 139724467616960 block7_sepconv3_bn: BatchNormalization 139724467238784->139724467616960 139724467616960->139724467530048 139724466361288 block8_sepconv1_act: Activation 139724467530048->139724466361288 139724468709920 add_19: Add 139724467530048->139724468709920 139724467586776 block8_sepconv1: SeparableConv2D 139724466361288->139724467586776 139724467848976 block8_sepconv1_bn: BatchNormalization 139724467586776->139724467848976 139724467816208 block8_sepconv2_act: Activation 139724467848976->139724467816208 139724467756224 block8_sepconv2: SeparableConv2D 139724467816208->139724467756224 139724468166160 block8_sepconv2_bn: BatchNormalization 139724467756224->139724468166160 139724467991048 block8_sepconv3_act: Activation 139724468166160->139724467991048 139724467756336 block8_sepconv3: SeparableConv2D 139724467991048->139724467756336 139724468400024 block8_sepconv3_bn: BatchNormalization 139724467756336->139724468400024 139724468400024->139724468709920 139724467586160 block9_sepconv1_act: Activation 139724468709920->139724467586160 139724469469536 add_20: Add 139724468709920->139724469469536 139724468283096 block9_sepconv1: SeparableConv2D 139724467586160->139724468283096 139724468636304 block9_sepconv1_bn: BatchNormalization 139724468283096->139724468636304 139724468659088 block9_sepconv2_act: Activation 139724468636304->139724468659088 139724468921456 block9_sepconv2: SeparableConv2D 139724468659088->139724468921456 139724468870896 block9_sepconv2_bn: BatchNormalization 139724468921456->139724468870896 139724469213728 block9_sepconv3_act: Activation 139724468870896->139724469213728 139724468511688 block9_sepconv3: SeparableConv2D 139724469213728->139724468511688 139724469128944 block9_sepconv3_bn: BatchNormalization 139724468511688->139724469128944 139724469128944->139724469469536 139724468282200 block10_sepconv1_act: Activation 139724469469536->139724468282200 139724470167256 add_21: Add 139724469469536->139724470167256 139724469008872 block10_sepconv1: SeparableConv2D 139724468282200->139724469008872 139724469361240 block10_sepconv1_bn: BatchNormalization 139724469008872->139724469361240 139724469379760 block10_sepconv2_act: Activation 139724469361240->139724469379760 139724469727864 block10_sepconv2: SeparableConv2D 139724469379760->139724469727864 139724469591904 block10_sepconv2_bn: BatchNormalization 139724469727864->139724469591904 139724469930136 block10_sepconv3_act: Activation 139724469591904->139724469930136 139724469727360 block10_sepconv3: SeparableConv2D 139724469930136->139724469727360 139724469816400 block10_sepconv3_bn: BatchNormalization 139724469727360->139724469816400 139724469816400->139724470167256 139724469009152 block11_sepconv1_act: Activation 139724470167256->139724469009152 139724470951720 add_22: Add 139724470167256->139724470951720 139724470234640 block11_sepconv1: SeparableConv2D 139724469009152->139724470234640 139724470049592 block11_sepconv1_bn: BatchNormalization 139724470234640->139724470049592 139724470080680 block11_sepconv2_act: Activation 139724470049592->139724470080680 139724470461832 block11_sepconv2: SeparableConv2D 139724470080680->139724470461832 139724470287888 block11_sepconv2_bn: BatchNormalization 139724470461832->139724470287888 139724470692048 block11_sepconv3_act: Activation 139724470287888->139724470692048 139724470663040 block11_sepconv3: SeparableConv2D 139724470692048->139724470663040 139724471070672 block11_sepconv3_bn: BatchNormalization 139724470663040->139724471070672 139724471070672->139724470951720 139724470232904 block12_sepconv1_act: Activation 139724470951720->139724470232904 139724471648496 add_23: Add 139724470951720->139724471648496 139724470870872 block12_sepconv1: SeparableConv2D 139724470232904->139724470870872 139724471274800 block12_sepconv1_bn: BatchNormalization 139724470870872->139724471274800 139724471152592 block12_sepconv2_act: Activation 139724471274800->139724471152592 139724471093568 block12_sepconv2: SeparableConv2D 139724471152592->139724471093568 139724471500080 block12_sepconv2_bn: BatchNormalization 139724471093568->139724471500080 139724471387192 block12_sepconv3_act: Activation 139724471500080->139724471387192 139724471354424 block12_sepconv3: SeparableConv2D 139724471387192->139724471354424 139724471711336 block12_sepconv3_bn: BatchNormalization 139724471354424->139724471711336 139724471711336->139724471648496 139724681619776 block13_sepconv1_act: Activation 139724471648496->139724681619776 139724681765608 conv2d_8: Conv2D 139724471648496->139724681765608 139724681531744 block13_sepconv1: SeparableConv2D 139724681619776->139724681531744 139724681913680 block13_sepconv1_bn: BatchNormalization 139724681531744->139724681913680 139724682262736 block13_sepconv2_act: Activation 139724681913680->139724682262736 139724681560920 block13_sepconv2: SeparableConv2D 139724682262736->139724681560920 139724682145520 block13_sepconv2_bn: BatchNormalization 139724681560920->139724682145520 139724682495088 block13_pool: MaxPooling2D 139724682145520->139724682495088 139724681648672 batch_normalization_8: BatchNormalization 139724681765608->139724681648672 139724682550184 add_24: Add 139724682495088->139724682550184 139724681648672->139724682550184 139724682783040 block14_sepconv1: SeparableConv2D 139724682550184->139724682783040 139724682817264 block14_sepconv1_bn: BatchNormalization 139724682783040->139724682817264 139724682672784 block14_sepconv1_act: Activation 139724682817264->139724682672784 139724682350096 block14_sepconv2: SeparableConv2D 139724682672784->139724682350096 139724682643888 block14_sepconv2_bn: BatchNormalization 139724682350096->139724682643888 139724682926848 block14_sepconv2_act: Activation 139724682643888->139724682926848 139724682348080 global_average_pooling2d_1: GlobalAveragePooling2D 139724682926848->139724682348080 139724833145072 dense_1: Dense 139724682348080->139724833145072

四、训练网络

我们会在xception基础上进行fine_tune。

4.1 回调函数

history用于记录训练过程中train_loss和val_loss,earlyStopping用于当检测值不在改善时终止训练

In [14]:
from keras import callbacks
class LossHistory(callbacks.Callback):
    def __init__(self):
        self.epoch = 0
    
    def on_train_begin(self, logs={}):
        self.losses = []
        self.val_losses = []
        self.acc = []
        self.val_acc = []
        self.epoch = 0

    def on_epoch_begin(self, batch, logs={}):
        self.epoch += 1
        
    def on_epoch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))
        self.val_losses.append(logs.get('val_loss'))
        self.acc.append(logs.get('acc'))
        self.val_acc.append(logs.get('val_acc'))
        model.save('xception_fine-tune_epoch{}.h5'.format(self.epoch))

history = LossHistory()
earlyStopping = callbacks.EarlyStopping(monitor='val_loss', patience=3, verbose=0, mode='auto')

4.2 实现loss、acc可视化函数

In [17]:
def show_loss_and_acc(title_name):
    loss = history.losses
    val_loss = history.val_losses
    plt.xlabel('Epochs')
    plt.ylabel('Loss')
    plt.title('Loss Trend: '+ title_name)
    plt.plot(loss, 'blue', label='Training Loss')
    plt.plot(val_loss, 'green', label='Validation Loss')
    plt.xticks(range(0, history.epoch),range(0, history.epoch+1))
    plt.legend()
    plt.show()
    
    acc = history.acc
    val_acc = history.val_acc
    plt.xlabel('Epochs')
    plt.ylabel('acc')
    plt.title('acc Trend: ' + title_name)
    plt.plot(acc, 'blue', label='Training acc')
    plt.plot(val_acc, 'green', label='Validation acc')
    plt.xticks(range(0, history.epoch),range(0, history.epoch+1))
    plt.legend()
    plt.show()

4.3 设置超参

In [15]:
epochs = 30
batch_size = 32
nb_validation_samples = math.ceil(len(train_image_list)/ 5)
nb_train_samples = 4 * nb_validation_samples

4.4 fine_tune Xception

实验一 、adam优化器,lr=0.0001,每次只放开2个block

步骤一:冻结Xception所有层,只训练top layers
In [16]:
#冻结Xception所有层,值训练top layers
for layer in base_model.layers:
    layer.trainable = False   
#编译模型    
from keras.optimizers import Adam
model.compile(optimizer=Adam(lr=0.0001), loss='binary_crossentropy', metrics=['accuracy'])
#图片数据增强
from keras.preprocessing.image import ImageDataGenerator
#训练数据增强
train_datagen = ImageDataGenerator( preprocessing_function=xception.preprocess_input, 
                                    shear_range=0.2, 
                                    zoom_range=0.2, 
                                    horizontal_flip=True)
#验证数据增强
validation_datagen = ImageDataGenerator(preprocessing_function=xception.preprocess_input)

train_generator = train_datagen.flow(x = train_X,
                                     y = train_Y,
                                     batch_size = batch_size,
                                     shuffle=True)
validation_generator = validation_datagen.flow( x = val_X,
                                               y = val_Y,
                                               batch_size = batch_size, 
                                               shuffle=False)
#训练模型
model.fit_generator(train_generator, 
                    steps_per_epoch=math.ceil(nb_train_samples/batch_size),
                    epochs=epochs, 
                    validation_data=validation_generator, 
                    validation_steps=math.ceil(nb_validation_samples/batch_size),
                    callbacks=[history, earlyStopping])
Epoch 1/30
624/624 [==============================] - 539s 864ms/step - loss: 0.3420 - acc: 0.9252 - val_loss: 0.1985 - val_acc: 0.9695
Epoch 2/30
624/624 [==============================] - 524s 840ms/step - loss: 0.1448 - acc: 0.9778 - val_loss: 0.1396 - val_acc: 0.9735
Epoch 3/30
624/624 [==============================] - 511s 818ms/step - loss: 0.1025 - acc: 0.9798 - val_loss: 0.1097 - val_acc: 0.9781
Epoch 4/30
624/624 [==============================] - 508s 813ms/step - loss: 0.0834 - acc: 0.9813 - val_loss: 0.0883 - val_acc: 0.9824
Epoch 5/30
624/624 [==============================] - 508s 814ms/step - loss: 0.0723 - acc: 0.9832 - val_loss: 0.0939 - val_acc: 0.9783
Epoch 6/30
624/624 [==============================] - 508s 814ms/step - loss: 0.0630 - acc: 0.9839 - val_loss: 0.0853 - val_acc: 0.9798
Epoch 7/30
624/624 [==============================] - 507s 813ms/step - loss: 0.0615 - acc: 0.9827 - val_loss: 0.0827 - val_acc: 0.9802
Epoch 8/30
624/624 [==============================] - 509s 816ms/step - loss: 0.0536 - acc: 0.9854 - val_loss: 0.0689 - val_acc: 0.9846
Epoch 9/30
624/624 [==============================] - 508s 814ms/step - loss: 0.0520 - acc: 0.9852 - val_loss: 0.0707 - val_acc: 0.9834
Epoch 10/30
624/624 [==============================] - 510s 817ms/step - loss: 0.0506 - acc: 0.9846 - val_loss: 0.0705 - val_acc: 0.9830
Epoch 11/30
624/624 [==============================] - 509s 816ms/step - loss: 0.0474 - acc: 0.9858 - val_loss: 0.0697 - val_acc: 0.9826
Out[16]:
<keras.callbacks.History at 0x7ff079f06470>
In [43]:
show_loss_and_acc("adam_train_cla")

由以上log信息可以看出,当只训练顶部的分类器时,第8代结束后val_loss最低,且经过3个epoch都没有比第8代更低,提前结束了训练。下面我们将加载第8个epoch结束后的model继续训练。

In [17]:
from keras.models import load_model
del model
model = load_model("xception_fine-tune_epoch8.h5")
步骤二:这次冻结前12个block,也就是要锁住前面的115层,然后放开后边2个block的所有层
In [18]:
#这次冻结前12个block,也就是要锁住前面的115层,然后放开后边2个block的所有层
for layer in model.layers[:116]:
    layer.trainable = False
for layer in model.layers[116:]:
    layer.trainable = True

#重新编译,模型
# model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='binary_crossentropy', metrics=['accuracy'])
model.compile(optimizer=Adam(lr=0.0001), loss='binary_crossentropy', metrics=['accuracy'])
#训练模型
model.fit_generator(train_generator, 
                    steps_per_epoch=math.ceil(nb_train_samples/batch_size),
                    epochs=epochs, 
                    validation_data=validation_generator, 
                    validation_steps=math.ceil(nb_validation_samples/batch_size),
                    callbacks=[history, earlyStopping])
Epoch 1/30
624/624 [==============================] - 591s 947ms/step - loss: 0.0314 - acc: 0.9887 - val_loss: 0.0171 - val_acc: 0.9948
Epoch 2/30
624/624 [==============================] - 587s 941ms/step - loss: 0.0161 - acc: 0.9943 - val_loss: 0.0139 - val_acc: 0.9962
Epoch 3/30
624/624 [==============================] - 587s 940ms/step - loss: 0.0088 - acc: 0.9971 - val_loss: 0.0144 - val_acc: 0.9954
Epoch 4/30
624/624 [==============================] - 587s 940ms/step - loss: 0.0065 - acc: 0.9978 - val_loss: 0.0159 - val_acc: 0.9960
Epoch 5/30
624/624 [==============================] - 587s 940ms/step - loss: 0.0056 - acc: 0.9978 - val_loss: 0.0249 - val_acc: 0.9936
Out[18]:
<keras.callbacks.History at 0x7ff079ec7fd0>
In [51]:
show_loss_and_acc("adam_train_top2")

由以上log信息可以看出,当放开顶端2个block时,第2代结束后val_loss最低,且经过3个epoch都没有比第2代更低,提前结束了训练。下面我们将加载第2个epoch结束后的model继续训练。

In [19]:
del model
model = load_model("xception_fine-tune_epoch2.h5")
步骤三:这次冻结前10个block,也就是要锁住前面的95层,然后放开后边4个block的所有层
In [20]:
#这次冻结前10个block,也就是要锁住前面的95层,然后放开后边4个block的所有层
for layer in model.layers[:96]:
    layer.trainable = False
for layer in model.layers[96:]:
    layer.trainable = True
#编译模型    
model.compile(optimizer=Adam(lr=0.0001), loss='binary_crossentropy', metrics=['accuracy'])

#训练模型
model.fit_generator(train_generator, 
                    steps_per_epoch=math.ceil(nb_train_samples/batch_size),
                    epochs=epochs, 
                    validation_data=validation_generator, 
                    validation_steps=math.ceil(nb_validation_samples/batch_size),
                    callbacks=[history, earlyStopping])
Epoch 1/30
624/624 [==============================] - 697s 1s/step - loss: 0.0134 - acc: 0.9953 - val_loss: 0.0265 - val_acc: 0.9924
Epoch 2/30
624/624 [==============================] - 690s 1s/step - loss: 0.0082 - acc: 0.9973 - val_loss: 0.0143 - val_acc: 0.9954
Epoch 3/30
624/624 [==============================] - 691s 1s/step - loss: 0.0040 - acc: 0.9986 - val_loss: 0.0186 - val_acc: 0.9940
Epoch 4/30
624/624 [==============================] - 691s 1s/step - loss: 0.0041 - acc: 0.9984 - val_loss: 0.0171 - val_acc: 0.9960
Epoch 5/30
624/624 [==============================] - 692s 1s/step - loss: 0.0036 - acc: 0.9988 - val_loss: 0.0181 - val_acc: 0.9952
Out[20]:
<keras.callbacks.History at 0x7fe89e23efd0>
In [49]:
show_loss_and_acc("adam_train_top4")

由以上log信息可以看出,当放开顶端4个block时,第2代结束后val_loss最低,且经过3个epoch都没有比第2代更低,提前结束了训练。

实验二 、adam优化器,默认参数,每次只放开2个block

步骤一:冻结Xception所有层,只训练top layers
In [33]:
#冻结Xception所有层,值训练top layers
for layer in base_model.layers:
    layer.trainable = False   
#编译模型    
from keras.optimizers import Adam
model.compile(optimizer=Adam(), loss='binary_crossentropy', metrics=['accuracy'])
#图片数据增强
from keras.preprocessing.image import ImageDataGenerator
#训练数据增强
train_datagen = ImageDataGenerator( preprocessing_function=xception.preprocess_input, 
                                    shear_range=0.2, 
                                    zoom_range=0.2, 
                                    horizontal_flip=True)
#验证数据增强
validation_datagen = ImageDataGenerator(preprocessing_function=xception.preprocess_input)

train_generator = train_datagen.flow(x = train_X,
                                     y = train_Y,
                                     batch_size = batch_size,
                                     shuffle=True)
validation_generator = validation_datagen.flow( x = val_X,
                                               y = val_Y,
                                               batch_size = batch_size, 
                                               shuffle=False)
#训练模型
model.fit_generator(train_generator, 
                    steps_per_epoch=math.ceil(nb_train_samples/batch_size),
                    epochs=epochs, 
                    validation_data=validation_generator, 
                    validation_steps=math.ceil(nb_validation_samples/batch_size),
                    callbacks=[history, earlyStopping])
Epoch 1/20
624/624 [==============================] - 496s 795ms/step - loss: 0.1074 - acc: 0.9734 - val_loss: 0.0979 - val_acc: 0.9745
Epoch 2/20
624/624 [==============================] - 486s 778ms/step - loss: 0.0467 - acc: 0.9855 - val_loss: 0.0635 - val_acc: 0.9838
Epoch 3/20
624/624 [==============================] - 488s 782ms/step - loss: 0.0410 - acc: 0.9861 - val_loss: 0.0806 - val_acc: 0.9779
Epoch 4/20
624/624 [==============================] - 484s 775ms/step - loss: 0.0399 - acc: 0.9873 - val_loss: 0.0757 - val_acc: 0.9798
Epoch 5/20
624/624 [==============================] - 492s 788ms/step - loss: 0.0390 - acc: 0.9867 - val_loss: 0.0549 - val_acc: 0.9858
Epoch 6/20
624/624 [==============================] - 483s 775ms/step - loss: 0.0355 - acc: 0.9879 - val_loss: 0.0974 - val_acc: 0.9711
Epoch 7/20
624/624 [==============================] - 491s 787ms/step - loss: 0.0358 - acc: 0.9880 - val_loss: 0.0533 - val_acc: 0.9852
Epoch 8/20
624/624 [==============================] - 484s 776ms/step - loss: 0.0351 - acc: 0.9882 - val_loss: 0.1027 - val_acc: 0.9703
Epoch 9/20
624/624 [==============================] - 484s 776ms/step - loss: 0.0335 - acc: 0.9893 - val_loss: 0.0550 - val_acc: 0.9856
Epoch 10/20
624/624 [==============================] - 491s 787ms/step - loss: 0.0355 - acc: 0.9875 - val_loss: 0.0537 - val_acc: 0.9860
Out[33]:
<keras.callbacks.History at 0x7f1d98c55908>
In [54]:
show_loss_and_acc("fine-tune-topClassifier")

由以上log信息可以看出,当只训练顶部的分类器时,第七代结束后val_loss最低,且经过3个epoch都没有比第七代更低,提前结束了训练。下面我们将加载第7个epoch结束后的model继续训练。

In [40]:
from keras.models import load_model
del model
model = load_model("xception_fine-tune_epoch7.h5")
model.save("xception_fine-tune_topCla.h5")
步骤二:这次冻结前12个block,也就是要锁住前面的115层,然后放开后边2个block的所有层
In [41]:
#这次冻结前12个block,也就是要锁住前面的115层,然后放开后边2个block的所有层
for layer in model.layers[:116]:
    layer.trainable = False
for layer in model.layers[116:]:
    layer.trainable = True

#重新编译,模型
model.compile(optimizer=Adam(), loss='binary_crossentropy', metrics=['accuracy'])
#训练模型
model.fit_generator(train_generator, 
                    steps_per_epoch=math.ceil(nb_train_samples/batch_size),
                    epochs=epochs, 
                    validation_data=validation_generator, 
                    validation_steps=math.ceil(nb_validation_samples/batch_size),
                    callbacks=[history, earlyStopping])
Epoch 1/20
624/624 [==============================] - 567s 909ms/step - loss: 0.0456 - acc: 0.9844 - val_loss: 0.0498 - val_acc: 0.9856
Epoch 2/20
624/624 [==============================] - 560s 897ms/step - loss: 0.0259 - acc: 0.9923 - val_loss: 0.0209 - val_acc: 0.9920
Epoch 3/20
624/624 [==============================] - 560s 897ms/step - loss: 0.0183 - acc: 0.9940 - val_loss: 0.0210 - val_acc: 0.9938
Epoch 4/20
624/624 [==============================] - 560s 897ms/step - loss: 0.0166 - acc: 0.9942 - val_loss: 0.0181 - val_acc: 0.9942
Epoch 5/20
624/624 [==============================] - 559s 896ms/step - loss: 0.0148 - acc: 0.9944 - val_loss: 0.0260 - val_acc: 0.9934
Epoch 6/20
624/624 [==============================] - 558s 895ms/step - loss: 0.0127 - acc: 0.9953 - val_loss: 0.0245 - val_acc: 0.9920
Epoch 7/20
624/624 [==============================] - 560s 897ms/step - loss: 0.0139 - acc: 0.9958 - val_loss: 0.0124 - val_acc: 0.9958
Epoch 8/20
624/624 [==============================] - 560s 897ms/step - loss: 0.0105 - acc: 0.9961 - val_loss: 0.0112 - val_acc: 0.9962
Epoch 9/20
624/624 [==============================] - 558s 895ms/step - loss: 0.0082 - acc: 0.9972 - val_loss: 0.1153 - val_acc: 0.9761
Epoch 10/20
624/624 [==============================] - 563s 903ms/step - loss: 0.0068 - acc: 0.9971 - val_loss: 0.0143 - val_acc: 0.9956
Epoch 11/20
624/624 [==============================] - 574s 921ms/step - loss: 0.0086 - acc: 0.9974 - val_loss: 0.0112 - val_acc: 0.9954
Epoch 12/20
624/624 [==============================] - 571s 915ms/step - loss: 0.0071 - acc: 0.9974 - val_loss: 0.0154 - val_acc: 0.9940
Epoch 13/20
624/624 [==============================] - 574s 921ms/step - loss: 0.0042 - acc: 0.9985 - val_loss: 0.0208 - val_acc: 0.9950
Epoch 14/20
624/624 [==============================] - 574s 921ms/step - loss: 0.0059 - acc: 0.9983 - val_loss: 0.0318 - val_acc: 0.9902
Out[41]:
<keras.callbacks.History at 0x7f157833d470>
In [58]:
show_loss_and_acc('xception_fine-tune_1314block')

由以上log信息可以看出,当放开model后边2个block的时,第8代结束后val_loss最低。下面我们将加载第8个epoch结束后的model继续训练。

In [49]:
del model
model = load_model("xception_fine-tune_epoch8.h5")
model.save('xception_fine-tune_1314block.h5')
步骤三:这次冻结前10个block,也就是要锁住前面的95层,然后放开后边4个block的所有层
In [50]:
#这次冻结前10个block,也就是要锁住前面的95层,然后放开后边4个block的所有层
for layer in model.layers[:96]:
    layer.trainable = False
for layer in model.layers[96:]:
    layer.trainable = True

#重新编译,模型
model.compile(optimizer=Adam(lr=0.0001), loss='binary_crossentropy', metrics=['accuracy'])
#训练模型
model.fit_generator(train_generator, 
                    steps_per_epoch=math.ceil(nb_train_samples/batch_size),
                    epochs=epochs, 
                    validation_data=validation_generator, 
                    validation_steps=math.ceil(nb_validation_samples/batch_size),
                    callbacks=[history, earlyStopping])
Epoch 1/20
624/624 [==============================] - 687s 1s/step - loss: 0.0078 - acc: 0.9974 - val_loss: 0.0130 - val_acc: 0.9950
Epoch 2/20
624/624 [==============================] - 676s 1s/step - loss: 0.0048 - acc: 0.9986 - val_loss: 0.0100 - val_acc: 0.9954
Epoch 3/20
624/624 [==============================] - 676s 1s/step - loss: 0.0035 - acc: 0.9990 - val_loss: 0.0137 - val_acc: 0.9962
Epoch 4/20
624/624 [==============================] - 677s 1s/step - loss: 0.0021 - acc: 0.9991 - val_loss: 0.0123 - val_acc: 0.9960
Epoch 5/20
624/624 [==============================] - 677s 1s/step - loss: 0.0024 - acc: 0.9992 - val_loss: 0.0119 - val_acc: 0.9952
Out[50]:
<keras.callbacks.History at 0x7f1554b7dc18>

由以上log信息可以看出,当放开model后边4个block的时,第2代结束后val_loss最低,已经达到了0.0100。将其对应的模型

In [51]:
del model
model = load_model("xception_fine-tune_epoch2.h5")
model.save('xception_fine-tune_11-14block.h5')
In [61]:
show_loss_and_acc("xception_fine-tune_11-14block")

利用此模型对test测试集进行预测,将结果提交kaggle得到了0.04734的成绩。但验证集loss呈现出锯齿状.

实验三 、adam优化器,学习率lr=0.0001,一次性放开后边4个block

In [17]:
#这次冻结前10个block,也就是要锁住前面的95层,然后放开后边4个block的所有层
for layer in model.layers[:96]:
    layer.trainable = False
for layer in model.layers[96:]:
    layer.trainable = True
#编译模型    
from keras.optimizers import Adam
model.compile(optimizer=Adam(lr=0.0001), loss='binary_crossentropy', metrics=['accuracy'])
#图片数据增强
from keras.preprocessing.image import ImageDataGenerator
#训练数据增强
train_datagen = ImageDataGenerator( preprocessing_function=xception.preprocess_input, 
                                    shear_range=0.2, 
                                    zoom_range=0.2, 
                                    horizontal_flip=True)
#验证数据增强
validation_datagen = ImageDataGenerator(preprocessing_function=xception.preprocess_input)

train_generator = train_datagen.flow(x = train_X,
                                     y = train_Y,
                                     batch_size = batch_size,
                                     shuffle=True)
validation_generator = validation_datagen.flow( x = val_X,
                                               y = val_Y,
                                               batch_size = batch_size, 
                                               shuffle=False)
#训练模型
model.fit_generator(train_generator, 
                    steps_per_epoch=math.ceil(nb_train_samples/batch_size),
                    epochs=epochs, 
                    validation_data=validation_generator, 
                    validation_steps=math.ceil(nb_validation_samples/batch_size),
                    callbacks=[history, earlyStopping])
Epoch 1/30
624/624 [==============================] - 705s 1s/step - loss: 0.0405 - acc: 0.9874 - val_loss: 0.0161 - val_acc: 0.9946
Epoch 2/30
624/624 [==============================] - 696s 1s/step - loss: 0.0113 - acc: 0.9964 - val_loss: 0.0148 - val_acc: 0.9952
Epoch 3/30
624/624 [==============================] - 697s 1s/step - loss: 0.0061 - acc: 0.9979 - val_loss: 0.0130 - val_acc: 0.9954
Epoch 4/30
624/624 [==============================] - 697s 1s/step - loss: 0.0072 - acc: 0.9978 - val_loss: 0.0116 - val_acc: 0.9962
Epoch 5/30
624/624 [==============================] - 697s 1s/step - loss: 0.0026 - acc: 0.9993 - val_loss: 0.0105 - val_acc: 0.9972
Epoch 6/30
624/624 [==============================] - 696s 1s/step - loss: 0.0044 - acc: 0.9985 - val_loss: 0.0140 - val_acc: 0.9958
Epoch 7/30
624/624 [==============================] - 696s 1s/step - loss: 0.0043 - acc: 0.9985 - val_loss: 0.0248 - val_acc: 0.9946
Epoch 8/30
624/624 [==============================] - 696s 1s/step - loss: 0.0037 - acc: 0.9988 - val_loss: 0.0120 - val_acc: 0.9968
Out[17]:
<keras.callbacks.History at 0x7faf62312908>
In [20]:
from keras.models import load_model
del model
model = load_model("xception_fine-tune_epoch5.h5")
model.save("xception_fine-tune_top4block.h5")
In [65]:
show_loss_and_acc("fine-tune-top4block")

利用此模型对test测试集进行预测,将结果提交kaggle得到了0.04833的成绩。

实验四:sgd优化器,一次性放开后4个block,lr=0.0001, momentum=0.9,进行训练

In [16]:
#这次冻结前10个block,也就是要锁住前面的95层,然后放开后边4个block的所有层
for layer in model.layers[:96]:
    layer.trainable = False
for layer in model.layers[96:]:
    layer.trainable = True
#编译模型    
from keras.optimizers import SGD
model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='binary_crossentropy', metrics=['accuracy'])
#图片数据增强
from keras.preprocessing.image import ImageDataGenerator
#训练数据增强
train_datagen = ImageDataGenerator( preprocessing_function=xception.preprocess_input, 
                                    shear_range=0.2, 
                                    zoom_range=0.2, 
                                    horizontal_flip=True)
#验证数据增强
validation_datagen = ImageDataGenerator(preprocessing_function=xception.preprocess_input)

train_generator = train_datagen.flow(x = train_X,
                                     y = train_Y,
                                     batch_size = batch_size,
                                     shuffle=True)
validation_generator = validation_datagen.flow( x = val_X,
                                               y = val_Y,
                                               batch_size = batch_size, 
                                               shuffle=False)
#训练模型
model.fit_generator(train_generator, 
                    steps_per_epoch=math.ceil(nb_train_samples/batch_size),
                    epochs=epochs, 
                    validation_data=validation_generator, 
                    validation_steps=math.ceil(nb_validation_samples/batch_size),
                    callbacks=[history, earlyStopping])
Epoch 1/30
624/624 [==============================] - 661s 1s/step - loss: 0.4483 - acc: 0.8829 - val_loss: 0.2604 - val_acc: 0.9888
Epoch 2/30
624/624 [==============================] - 653s 1s/step - loss: 0.2130 - acc: 0.9734 - val_loss: 0.1430 - val_acc: 0.9920
Epoch 3/30
624/624 [==============================] - 653s 1s/step - loss: 0.1392 - acc: 0.9783 - val_loss: 0.0940 - val_acc: 0.9940
Epoch 4/30
624/624 [==============================] - 653s 1s/step - loss: 0.1059 - acc: 0.9806 - val_loss: 0.0697 - val_acc: 0.9948
Epoch 5/30
624/624 [==============================] - 653s 1s/step - loss: 0.0847 - acc: 0.9838 - val_loss: 0.0549 - val_acc: 0.9962
Epoch 6/30
624/624 [==============================] - 653s 1s/step - loss: 0.0753 - acc: 0.9827 - val_loss: 0.0454 - val_acc: 0.9960
Epoch 7/30
624/624 [==============================] - 653s 1s/step - loss: 0.0653 - acc: 0.9840 - val_loss: 0.0389 - val_acc: 0.9960
Epoch 8/30
624/624 [==============================] - 653s 1s/step - loss: 0.0623 - acc: 0.9840 - val_loss: 0.0343 - val_acc: 0.9964
Epoch 9/30
624/624 [==============================] - 653s 1s/step - loss: 0.0561 - acc: 0.9849 - val_loss: 0.0308 - val_acc: 0.9964
Epoch 10/30
624/624 [==============================] - 653s 1s/step - loss: 0.0525 - acc: 0.9862 - val_loss: 0.0278 - val_acc: 0.9964
Epoch 11/30
624/624 [==============================] - 653s 1s/step - loss: 0.0459 - acc: 0.9878 - val_loss: 0.0257 - val_acc: 0.9962
Epoch 12/30
624/624 [==============================] - 653s 1s/step - loss: 0.0468 - acc: 0.9874 - val_loss: 0.0240 - val_acc: 0.9964
Epoch 13/30
624/624 [==============================] - 653s 1s/step - loss: 0.0441 - acc: 0.9868 - val_loss: 0.0226 - val_acc: 0.9964
Epoch 14/30
624/624 [==============================] - 653s 1s/step - loss: 0.0428 - acc: 0.9877 - val_loss: 0.0212 - val_acc: 0.9964
Epoch 15/30
624/624 [==============================] - 653s 1s/step - loss: 0.0394 - acc: 0.9888 - val_loss: 0.0201 - val_acc: 0.9964
Epoch 16/30
624/624 [==============================] - 653s 1s/step - loss: 0.0398 - acc: 0.9883 - val_loss: 0.0192 - val_acc: 0.9964
Epoch 17/30
624/624 [==============================] - 653s 1s/step - loss: 0.0371 - acc: 0.9894 - val_loss: 0.0185 - val_acc: 0.9964
Epoch 18/30
624/624 [==============================] - 652s 1s/step - loss: 0.0349 - acc: 0.9897 - val_loss: 0.0178 - val_acc: 0.9964
Epoch 19/30
624/624 [==============================] - 652s 1s/step - loss: 0.0377 - acc: 0.9885 - val_loss: 0.0171 - val_acc: 0.9964
Epoch 20/30
624/624 [==============================] - 652s 1s/step - loss: 0.0364 - acc: 0.9885 - val_loss: 0.0167 - val_acc: 0.9964
Epoch 21/30
624/624 [==============================] - 652s 1s/step - loss: 0.0341 - acc: 0.9888 - val_loss: 0.0163 - val_acc: 0.9964
Epoch 22/30
624/624 [==============================] - 652s 1s/step - loss: 0.0320 - acc: 0.9901 - val_loss: 0.0158 - val_acc: 0.9964
Epoch 23/30
624/624 [==============================] - 652s 1s/step - loss: 0.0319 - acc: 0.9901 - val_loss: 0.0154 - val_acc: 0.9966
Epoch 24/30
624/624 [==============================] - 652s 1s/step - loss: 0.0336 - acc: 0.9897 - val_loss: 0.0151 - val_acc: 0.9964
Epoch 25/30
624/624 [==============================] - 652s 1s/step - loss: 0.0322 - acc: 0.9898 - val_loss: 0.0149 - val_acc: 0.9966
Epoch 26/30
624/624 [==============================] - 652s 1s/step - loss: 0.0323 - acc: 0.9899 - val_loss: 0.0146 - val_acc: 0.9964
Epoch 27/30
624/624 [==============================] - 652s 1s/step - loss: 0.0308 - acc: 0.9902 - val_loss: 0.0144 - val_acc: 0.9966
Epoch 28/30
624/624 [==============================] - 653s 1s/step - loss: 0.0313 - acc: 0.9910 - val_loss: 0.0141 - val_acc: 0.9964
Epoch 29/30
624/624 [==============================] - 653s 1s/step - loss: 0.0276 - acc: 0.9912 - val_loss: 0.0138 - val_acc: 0.9964
Epoch 30/30
624/624 [==============================] - 653s 1s/step - loss: 0.0308 - acc: 0.9893 - val_loss: 0.0136 - val_acc: 0.9968
Out[16]:
<keras.callbacks.History at 0x7f14326ac470>
In [69]:
show_loss_and_acc("fine-tune-top4block_SGD")
In [19]:
model.save("fine-tune-top4block_SGD.h5")

利用此模型对test测试集进行预测,将结果提交kaggle得到了0.03974的成绩

五、预测测试集

利用训练好的模型对测试集进行预测,并将测试结果写入csv文件中,将csv文件上传kaggle验证最终结果。

In [20]:
import pandas as pd
from keras.applications import *
df = pd.read_csv("sample_submission.csv")
In [25]:
model_list = ["xception_fine-tune_11-14block.h5","xception_fine-tune_top4block.h5", "fine-tune-top4block_SGD.h5"]
from keras.models import load_model
for model_name in model_list:
    del model
    model = load_model(model_name)
    for batch_imgpath_list in batch_img(test_image_list, batch_size):
        X = read_batch_img(batch_imgpath_list)
        X = xception.preprocess_input(X)
        pred_y = model.predict_on_batch(X)
#         pred_y = pred_y.clip(min=0.001, max=0.999)
        pred_y = pred_y.clip(min=0.005, max=0.995)
#         pred_y = pred_y.clip(min=0.0005, max=0.9995)
#         pred_y = pred_y.clip(min=0.0001, max=0.9999)
        for i, filename in enumerate(batch_imgpath_list):
            index = int(filename.split('/')[-1].split('.')[0])
            df.at[index-1, 'label'] =  pred_y[i]
    df.to_csv('pred_'+ (model_name.split('.')[0] +'_Clip999.csv'), index=None)
展示预测结果
In [21]:
del model
model = load_model("fine-tune-top4block_SGD.h5")
In [35]:
def display_pred_img(img_list):
    fig = plt.figure(figsize=(15, 3 * math.ceil(len(img_list)/5)))
    X = read_batch_img(img_list)
    img = X
    X = xception.preprocess_input(X)
    pred_y = model.predict_on_batch(X)
    
    for i in range(0, len(img_list)):
        ax = fig.add_subplot(math.ceil(len(img_list)/5),5,i+1)
        if pred_y[i] >= 0.5:
            ax.set_title("{} : {:.2f}% is dog".format(os.path.basename(img_list[i]), pred_y[i][0] * 100))
        else:
            ax.set_title("{} : {:.2f}% is cat".format(os.path.basename(img_list[i]), (1-pred_y[i][0])*100))
        ax.set_xticks([])
        ax.set_yticks([])
        ax.imshow(img[i])
    plt.show()
    
dis_pred_img_list = test_image_list[:10] + test_image_list[-10:]
display_pred_img(dis_pred_img_list)
从网络上随机挑选了20张猫狗图片进行预测,检验模型的鲁棒性
In [75]:
del model
model = load_model("fine-tune-top4block_SGD.h5")
In [76]:
robustness_image_path="./robustness/"
robustness_image_list=[]    
get_image_list(robustness_image_path, robustness_image_list)
In [84]:
display_pred_img(robustness_image_list)